#pragma once

#include <linux/kconfig.h>
#include <linux/cache.h>
#include <linux/time.h>
#include <linux/limits.h>

#ifndef CONFIG_HZ
#define HZ 200
#else
#define HZ CONFIG_HZ
#endif

typedef union
{
    u64 jiffies_64;
    unsigned long jiffies_ul;
} jiffies_t;

extern jiffies_t _jiffies;

#define jiffies (_jiffies.jiffies_ul)

/**
 * time_after_eq - returns true if the time a is after or the same as time b.
 * @a: first comparable as unsigned long
 * @b: second comparable as unsigned long
 *
 * Return: %true is time a is after or the same as time b, otherwise %false.
 */
#define time_after_eq(a, b) \
    (((long)((a) - (b)) >= 0))

/**
 * time_before_eq - returns true if the time a is before or the same as time b.
 * @a: first comparable as unsigned long
 * @b: second comparable as unsigned long
 *
 * Return: %true is time a is before or the same as time b, otherwise %false.
 */
#define time_before_eq(a, b) time_after_eq(b, a)

unsigned long __msecs_to_jiffies(const int m);
unsigned long _msecs_to_jiffies(const unsigned int m);

/*
 * Change timeval to jiffies, trying to avoid the
 * most obvious overflows..
 *
 * And some not so obvious.
 *
 * Note that we don't want to return LONG_MAX, because
 * for various timeout reasons we often end up having
 * to wait "jiffies+1" in order to guarantee that we wait
 * at _least_ "jiffies" - so "jiffies+1" had better still
 * be positive.
 */
#define MAX_JIFFY_OFFSET (((~0 >> 1) >> 1) - 1)

#define msecs_to_jiffies(m) __msecs_to_jiffies(m)

/**
 * time_after - returns true if the time a is after time b.
 * @a: first comparable as unsigned long
 * @b: second comparable as unsigned long
 *
 * Do this with "<0" and ">=0" to only test the sign of the result. A
 * good compiler would generate better code (and a really good compiler
 * wouldn't care). Gcc is currently neither.
 *
 * Return: %true is time a is after time b, otherwise %false.
 */
#define time_after(a, b) \
     ((long)((b) - (a)) < 0)

/**
 * time_before - returns true if the time a is before time b.
 * @a: first comparable as unsigned long
 * @b: second comparable as unsigned long
 *
 * Return: %true is time a is before time b, otherwise %false.
 */
#define time_before(a, b) time_after(b, a)

void jiffies_increase(unsigned long ticks);

#define INITIAL_JIFFIES 0 //TODO

/**
 * time_is_after_jiffies - return true if a is after jiffies
 * @a: time (unsigned long) to compare to jiffies
 *
 * Return: %true is time a is after jiffies, otherwise %false.
 */
#define time_is_after_jiffies(a) time_before(jiffies, a)
